package com.icss.flow.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.icss.flow.enums.FieldTypeEnum;
import com.icss.flow.exception.CommonException;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.icss.flow.mapper.DynamicTableMapper;
import com.icss.flow.mapper.TMetaEntityMapper;
import com.icss.flow.mapper.TModuleMapper;
import com.icss.flow.pojo.dto.TMetaFieldCreateDto;
import com.icss.flow.pojo.dto.TMetaFieldDTO;
import com.icss.flow.pojo.dto.TMetaFieldUpdateDto;
import com.icss.flow.pojo.entity.TMetaEntity;
import com.icss.flow.pojo.entity.TMetaField;
import com.icss.flow.mapper.TMetaFieldMapper;
import com.icss.flow.pojo.vo.TMetaFieldModeleVO;
import com.icss.flow.pojo.vo.TMetaFieldVO;
import com.icss.flow.pojo.entity.TModule;

import com.icss.flow.service.TMetaFieldService;

import com.icss.flow.utils.MetaFieldUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import com.icss.flow.service.TModuleService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * 元数据实体字段表(TMetaField)表服务实现类
 *
 * @author makejava
 * @since 2024-01-30 13:05:58
 */
@Slf4j
@Service
public class TMetaFieldServiceImpl extends ServiceImpl<TMetaFieldMapper, TMetaField> implements TMetaFieldService {
    @Autowired
    private TMetaFieldMapper tMetaFieldMapper;

    @Autowired
    private TMetaEntityMapper tMetaEntityMapper;

    @Resource
    private DynamicTableMapper dynamicTableMapper;



    @Resource
    private TModuleService moduleService;



    /**
     * 根据entityCode获取对应实体主键字段
     * @param entityCode
     * @return
     */
    @Override
    public TMetaField getPrimaryKeyByEntityCode(Integer entityCode) {
        LambdaQueryWrapper<TMetaField> lqwField = new LambdaQueryWrapper<>();
        lqwField.eq(TMetaField::getEntityCode, entityCode).eq(TMetaField::getType, "PrimaryKey");
        return this.getOne(lqwField);
    }




    /**
     * 新增实体字段
     * @param entityCode 实体code
     * @param tMetaFieldCreateDto 实体dto
     */
    @Override
    public Boolean createMetaField(Integer entityCode, TMetaFieldCreateDto tMetaFieldCreateDto) {
        LambdaQueryWrapper<TMetaField> lqw = new LambdaQueryWrapper<>();
        lqw.eq(TMetaField::getEntityCode, entityCode).eq(TMetaField::getName, tMetaFieldCreateDto.getName());
        List<TMetaField> fieldList = tMetaFieldMapper.selectList(lqw);
        if(ObjectUtil.isNotEmpty(fieldList)){
            throw new CommonException("该字段已存在");
        }
        TMetaField tMetaField = BeanUtil.copyProperties(tMetaFieldCreateDto, TMetaField.class);
        tMetaField.setFieldId("0000002-" + UUID.randomUUID().toString().replace("-", ""));
        tMetaField.setEntityCode(entityCode);
        tMetaField.setPhysicalName(tMetaField.getName());
        tMetaField.setIdFieldFlag(0);
        tMetaField.setNameFieldFlag(0);
        tMetaField.setMainDetailFieldFlag(0);
        boolean save = this.save(tMetaField);
        LambdaQueryWrapper<TMetaEntity> lqwEntity = new LambdaQueryWrapper<>();
        lqwEntity.eq(TMetaEntity::getEntityCode, entityCode);
        TMetaEntity tMetaEntity = tMetaEntityMapper.selectOne(lqwEntity);
        if(ObjectUtil.isEmpty(tMetaEntity)){
            throw new CommonException("该实体不存在");
        }
        List<TModule> moduleList = moduleService.list();
        try {
            //查询控件类型表 设置字段对应数据库 字段类型
            TModule tModule = moduleList.stream().filter(item -> item.getModuleValue().equals(tMetaField.getType()))
                    .toList().stream().findFirst().orElseThrow(() -> new CommonException("未查询到当前字段对应控件type!"));
            tMetaField.setTypeSql(tModule.getSqlType());
            //追加实体字段到表结构
            dynamicTableMapper.appendEntityField(tMetaEntity.getPhysicalName(),new ArrayList<>(){{add(tMetaField);}});
        }catch (Exception e) {
            //追加异常删除该条字段
            this.removeById(tMetaField);
            log.error("追加字段异常tMetaField：{},e：{}",tMetaField,e);
            return false;
        }
        return true;
    }



    /***
     * 修改实体字段de
     * @param tMetaFieldUpdateDto 实体更新dto
     */
    @Override
    public Boolean updateMetaField(TMetaFieldUpdateDto tMetaFieldUpdateDto) {
        //查询未更新之前的字段数据
        TMetaField beforeTmetaField = tMetaFieldMapper.selectById(tMetaFieldUpdateDto.getAutoId());
        if(beforeTmetaField.getUpdatable()==1){
            throw new CommonException("当前字段为系统默认字段，不允许修改");
        }
        TMetaField tMetaField = BeanUtil.copyProperties(tMetaFieldUpdateDto, TMetaField.class);
        //查询实体数据
        LambdaQueryWrapper<TMetaEntity> lqw = new LambdaQueryWrapper<>();
        lqw.eq(TMetaEntity::getEntityCode,beforeTmetaField.getEntityCode());
        TMetaEntity tMetaEntity = tMetaEntityMapper.selectOne(lqw);


        List<TModule> moduleList = moduleService.list();
        //查询控件类型表 设置字段对应数据库 字段类型
        TModule tModule = moduleList.stream().filter(item -> item.getModuleValue().equals(tMetaField.getType())).toList().stream().findFirst().get();
        tMetaField.setTypeSql(tModule.getSqlType());
        this.updateById(tMetaField);
        try {
            //修改label 即字段注释
            dynamicTableMapper.alterEntityTable(tMetaEntity.getPhysicalName(),new ArrayList<>(){{add(tMetaField);}});
        }catch (Exception e){
            //更新表结构失败 进行数据回滚
            this.updateById(beforeTmetaField);
            log.error("修改字段异常tMetaField：{},e：{}",tMetaField,e);
            return false;
        }
            return true;
    }

    /***
     * 获取实体字段列表
     * @param entityCode 实体code
     * @return 实体字段vo
     */
    @Override
    public List<TMetaFieldVO> getMetaFieldList(Integer entityCode) {
        LambdaQueryWrapper<TMetaField> lqw = new LambdaQueryWrapper<>();
        lqw.eq(TMetaField::getEntityCode, entityCode);
        List<TMetaField> tMetaFieldList = this.list(lqw);
        if(CollectionUtil.isEmpty(tMetaFieldList)){
            throw new CommonException("当前对应实体字段不存在!");
        }
        return tMetaFieldList.stream().map(tMetaField -> {
            TMetaFieldVO tMetaFieldVO = new TMetaFieldVO();
            BeanUtil.copyProperties(tMetaField, tMetaFieldVO);
            tMetaFieldVO.setReserved(MetaFieldUtils.isReservedField(tMetaField));
            return tMetaFieldVO;
        }).toList();
    }

    /***
     * 逻辑删除实体字段
     * @param autoId
     * @return
     */
    @Override
    public Boolean deleteMetaField(Integer autoId) {
        TMetaField tMetaField = this.getById(autoId);
        if(tMetaField.getCreatable()==1){
            throw new CommonException("当前字段为系统默认字段，无法删除！");
        }
        return this.removeById(autoId);
    }
    /**
     * 通过主键修改字段数据
     *
     * @param json
     * @return
     */
    @Override
    public Boolean updateField(String json) {
        // 1. 解析json
        List<TMetaField> tMetaFieldList = this.analysisJsonMap(json);
        // 2. 查询旧字段
        String entityCode = tMetaFieldList.get(0).getEntityCode().toString();
        LambdaQueryWrapper<TMetaField> lqw = new LambdaQueryWrapper<>();
        lqw.eq(TMetaField::getEntityCode, entityCode);
        List<TMetaField> oldTmetaFieldList = tMetaFieldMapper.selectList(lqw);
        // 旧字段
        Set<String> oldFieldNameList = oldTmetaFieldList.stream()
                .map(TMetaField::getName)
                .collect(Collectors.toSet());
        // 新字段
        Set<String> fieldNameList = tMetaFieldList.stream()
                .map(TMetaField::getName)
                .collect(Collectors.toSet());

        // 2.1 删除字段
        for (TMetaField oldTmetaField : oldTmetaFieldList) {
            if (!fieldNameList.contains(oldTmetaField.getName())) {
                tMetaFieldMapper.deleteById(oldTmetaField.getAutoId());
            }
        }

        // 3. 批量更新字段
        for (TMetaField tMetaField : tMetaFieldList) {
            // 3.1 判断是否是新增字段
            if (!oldFieldNameList.contains(tMetaField.getName())) {
                tMetaFieldMapper.insert(tMetaField);
            } else {
                // 3.2 更新字段
                LambdaQueryWrapper<TMetaField> field = new LambdaQueryWrapper<>();
                field.eq(TMetaField::getName, tMetaField.getName());
                Integer autoId = tMetaFieldMapper.selectOne(field).getAutoId();
                tMetaField.setAutoId(autoId);
                baseMapper.updateById(tMetaField);
            }
        }
        return true;
    }

    // 解析json
    private List<TMetaField> analysisJsonMap(String json) {
        Gson gson = new Gson();
        //  解析json
        JsonObject jsonObject = gson.fromJson(json, JsonObject.class);
        //  获取entityCode
        Integer entityCode = jsonObject.get("entityCode").getAsInt();
        //  获取字段列表
        JsonArray fieldList = jsonObject.getAsJsonArray("fieldList");
        //  解析字段列表
        return gettMetaFieldDTOList(gson, fieldList, entityCode);
    }

    // 解析字段列表
    private List<TMetaField> gettMetaFieldDTOList(Gson gson, JsonArray fieldList, Integer entityCode) {
        List<TMetaField> updateFieldList = new ArrayList<>();
        for (int i = 0; i < fieldList.size(); i++) {
            JsonObject field = fieldList.get(i).getAsJsonObject();
            TMetaFieldDTO tMetaFieldDTO = gson.fromJson(field, TMetaFieldDTO.class);
            TMetaField tMetaField = new TMetaField();
            tMetaField.setAutoId(tMetaFieldDTO.getAutoId());
            tMetaField.setLabel(tMetaFieldDTO.getInfo());
            tMetaField.setName(tMetaFieldDTO.getTitle());
            // 设置默认值0
            tMetaField.setFieldId("0000002-" + UUID.randomUUID().toString().replace("-", ""));
            tMetaField.setPhysicalName("0");
            tMetaField.setType("0");
            tMetaField.setNullable(0);
            tMetaField.setCreatable(0);
            tMetaField.setUpdatable(0);
            tMetaField.setIdFieldFlag(0);
            tMetaField.setNameFieldFlag(0);
            tMetaField.setMainDetailFieldFlag(0);
            tMetaField.setDefaultMemberOfListFlag(0);
            tMetaField.setReferTo("0");
            tMetaField.setEntityCode(entityCode);
            updateFieldList.add(tMetaField);
        }
        return updateFieldList;
    }


    /**
     * 通过主键查询单条数据
     *
     * @param entityCode 主键
     * @return 单条数据
     */
    @Override
    public List<TMetaFieldModeleVO> queryFieldById(Integer entityCode) {
        return tMetaFieldMapper.selectListField(entityCode);
    }
}
